﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Text;

using FRL.DebtChased.Extensions;

namespace FRL.DebtChased.Repository.ViewModels
{

	/// <summary>
	/// Declaration of ClientCollectorAssignmentsModel class
	/// </summary>
	[Serializable]
	public class ClientCollectorAssignmentsModel
	{

		/////////////////////////////////////////////////////////////
		// Nested classes

		[Serializable]
		public class Element
		{

			/////////////////////////////////////////////////////////
			// Attributes

			internal int m_iClientCollectorAssignmentId = 0;
			public int ClientCollectorAssignmentId
			{
				get { return m_iClientCollectorAssignmentId; }
			}

			internal int m_iUserId = 0;
			public int UserId
			{
				get { return m_iUserId; }
				set { m_iUserId = value; }
			}
			internal string m_strUserAsText;
			public string UserAsText
			{
				get { return m_strUserAsText; }
			}

			internal decimal m_dcMin = 0;
			public decimal Min
			{
				get { return m_dcMin; }
				set { m_dcMin = value; }
			}

			internal bool m_bHasMaximum;
			public bool HasMaximum
			{
				get { return m_bHasMaximum; }
				set { m_bHasMaximum = value; }
			}

			internal decimal m_dcMax = 0;
			public decimal Max
			{
				get { return m_dcMax; }
				set { m_dcMax = value; }
			}

			public string FilterAsText
			{
				get 
				{
					if ((m_dcMin == 0) && (m_dcMax == ClientCollectorAssignments.MaximumDecimalCode))
						return Definitions.All;
					else if ((m_dcMin == 0) && (m_dcMax != ClientCollectorAssignments.MaximumDecimalCode))
						return string.Format("Up to {0:#,0.00}",m_dcMax);
					else if (m_dcMax == ClientCollectorAssignments.MaximumDecimalCode)
						return string.Format("From {0:#,0.00}",m_dcMin);
					else
						return string.Format("From {0:#,0.00} To {1:#,0.00}", m_dcMin,m_dcMax);
				}
			}

			internal string m_strModifiedAsText;
			public string ModifiedAsText
			{
				get { return m_strModifiedAsText; }
			}

			/////////////////////////////////////////////////////////
			// Attributes

			public Element(int iClientCollectorAssignmentId)
			{

				// Initialize member variables
				m_iClientCollectorAssignmentId = iClientCollectorAssignmentId;

			}

		}

		/////////////////////////////////////////////////////////////
		// Attributes

		internal int? m_iClientId = 0;
		public int? ClientId
		{
			get { return m_iClientId; }
		}

		private List<Element> m_elements = new List<Element>();
		public List<Element> Elements
		{
			get { return m_elements; }
		}

		/////////////////////////////////////////////////////////////
		// Construction

		public ClientCollectorAssignmentsModel(DebtChasedEntities ent, int? iClientId)
		{

			// Initialize member variables
			m_iClientId = iClientId;

			// Load assignments from store procedure
			var results = ent.ClientCollectorAssignmentsProc(m_iClientId);
			foreach (var ob in results)
			{

				// Add an element to the model
				Element el = new Element(ob.fdClientCollectorAssignmentId);
				el.m_iUserId = ob.fdUserId;
				el.m_strUserAsText = ob.fdUserAsText;
				el.m_dcMin = ob.fdMin;
				this.m_elements.Add(el);

				// Set maximum
				if (ob.fdMax == ClientCollectorAssignments.MaximumDecimalCode)
				{
					el.m_dcMax = ob.fdMin + 10000;
					el.m_bHasMaximum = false;
				}
				else
				{
					el.m_dcMax = ob.fdMax;
					el.m_bHasMaximum = true;
				}

				// Modified text
				if(ob.fdModifiedAt != null)
					el.m_strModifiedAsText = string.Format("{0} by {1}",
						ob.fdModifiedAt.Value.ToCuteString(),
						ob.fdModifiedBy
					);

			} // foreach-loop

		}

		/////////////////////////////////////////////////////////////
		// Operations

		public string Set(DebtChasedEntities ent, int iUserId)
		{

			// Declare return variable
			string strError = null;

			try
			{

				
				// Get the existing assignment list
				List<ClientCollectorAssignment> current = (from cca in ent.ClientCollectorAssignments
														   where (m_iClientId == null ? cca.ClientId == null : cca.ClientId == m_iClientId)
														   select cca).ToList();

				// Update the current items
				foreach (ClientCollectorAssignment assignment in current)
				{

					// Find in the model
					ClientCollectorAssignmentsModel.Element modelElement = this.FindByAssignmentId(assignment.ClientCollectorAssignmentId);

					// If model element found...
					if (modelElement != null)
					{

						// Get the true max value
						decimal dcTrueMax = modelElement.HasMaximum ? modelElement.m_dcMax : ClientCollectorAssignments.MaximumDecimalCode;

						// Compare details
						if (
							(modelElement.m_dcMin != assignment.Min)
							||
							(dcTrueMax != assignment.Max)
							||
							(modelElement.m_iUserId != assignment.UserId)
						)
						{

							// Update the assignment
							assignment.Min = modelElement.m_dcMin;
							assignment.Max = dcTrueMax;
							assignment.UserId = modelElement.m_iUserId;

						}

					}
					else
					{

						// Assignment has been deleted
						ent.ClientCollectorAssignments.DeleteObject(assignment);

					}

				}

				// Add new assignment
				foreach (ClientCollectorAssignmentsModel.Element el in this.Elements)
				{

					// If this status has a zero or negative 
					if (el.ClientCollectorAssignmentId <= 0)
					{

						// Add a new assignment to the database
						ClientCollectorAssignment newAssignment = ClientCollectorAssignment.CreateClientCollectorAssignment(
							0,
							el.m_iUserId,
							el.m_dcMin,
							el.HasMaximum ? el.m_dcMax : ClientCollectorAssignments.MaximumDecimalCode
						);
						newAssignment.ClientId = m_iClientId;
						ent.ClientCollectorAssignments.AddObject(newAssignment);

					}

				}

				// Save changes to the database
				ent.SaveChanges();

			}
			catch (Exception x)
			{

				// Process exception
				strError = ErrorProcessing.HandleException(x, "save client assignment", iUserId);

			}

			// Return variable
			return strError;

		}

		public ClientCollectorAssignmentsModel.Element FindByAssignmentId( int iClientCollectorAssignmentId )
		{

			// Declare return variable
			ClientCollectorAssignmentsModel.Element Ftmp = null;

			// Loop through elements
			foreach (ClientCollectorAssignmentsModel.Element el in this.m_elements)
			{
				if (el.m_iClientCollectorAssignmentId == iClientCollectorAssignmentId)
				{
					Ftmp = el;
					break;
				}
			}

			// Return variable
			return Ftmp;

		}

		public ClientCollectorAssignmentsModel.Element ContainsCollectorId(int iCollectorId)
		{

			// Declare return variable
			ClientCollectorAssignmentsModel.Element Ftmp = null;

			// Loop through elements
			foreach (ClientCollectorAssignmentsModel.Element el in this.m_elements)
			{
				if (el.UserId == iCollectorId)
				{
					Ftmp = el;
					break;
				}
			}

			// Return variable
			return Ftmp;

		}

		public int GetNextNewId()
		{

			// Declare return variable
			int iFtmp = 0;

			// Find the lowest id
			foreach (Element el in m_elements)
				iFtmp = Math.Min(iFtmp, el.ClientCollectorAssignmentId);
			iFtmp--;

			// Return variable
			return iFtmp;

		}

	}

}
